<template>
    <div style="width: 100%; height: 100%;">
      <el-input
        ref="searchInput"
        v-model="searchValue"
        placeholder="请输入搜索内容"
        :style="{
          width: '100%',
          margin: '8px 0px',
        }"
        autofocus
      />
  
      <template v-if="!loading">
        <RecycleScroller
          v-if="visibleData.length > 0"
          :style="{
            height: 'calc(100% - 32px - 16px)',
            'scroll-behavior': 'smooth',
          }"
          :key-field="nodeKey"
          :items="visibleData"
          :item-size="itemSize"
          :buffer="buffer"
          v-slot="{ item }"
        >
          <div
            class="virtual-tree__list-view"
            :style="{
              paddingLeft: 18 * (item.treeLevel) + 'px',
              height: itemSize + 'px'
            }"
          >
            <img 
              v-if="item.children && item.children.length"
              :style="{
                width: '12px',
                marginRight: '4px',
                transform: item.expand ? 'rotate(90deg)' : 'rotate(0deg)',
              }" src="../img/tree-triangle.svg" @click="toggleExpand(item)"/>     
            <span v-else style="width: 18px; display: inline-block; flex-shrink: 0"/>

            
            <el-checkbox
              v-model="item.checked"
              :indeterminate="item.indeterminate"
      
              @change="handleCheck(item)"
            />

            <img v-if="item.eyeVisible" @click="onEyeVisible(item, false)" style="width: 18px;" src="../img/open-eye.svg"/>
            <img v-else @click="onEyeVisible(item, true)" style="width: 18px;" src="../img/close-eye.svg"/>

            <span class="virtual-tree__title">{{ item.name || item.type }}</span>
          </div>
        </RecycleScroller>
        <div v-else class="not-found"> 暂无数据 </div>
      </template>
      <template v-else>
        <div class="loading">
          <i class="fa fa-spinner put-load-loop" style="margin-right: 4px" />
          <span>加载中</span>
        </div>
      </template>
    </div>
  </template>
  
  <script>
  import { RecycleScroller } from "vue-virtual-scroller";
  import { ElInput, ElCheckbox } from "element-plus";

  
  export default {
    components: {
      RecycleScroller,
      ElInput,
      ElCheckbox
    },
    props: {
      selectModelKeys:{
      type:Array,
        default:()=>[]
      },
      treeData: {
        type: Object,
        default: () => {
          return {};
        }
      }
    },
    emits: ['on-change'],
    data() {
      return {
        searchValue: "",
        loading: false,
        itemSize: 36,
        buffer: 100,
        nodeKey: "treeId",
        defaultExpandLevel: 0,
        dataList: [],
        checkIndexs: [],
        eyeIndexs: []
      };
    },
    computed: {
      visibleData() {
        return this.dataList.filter((i) => {
          if (this.searchValue) {
            return i.visible && i.name.toLowerCase().indexOf(this.searchValue.toLowerCase()) > -1
          } else {
            return i.visible 
          }
        });
      },
    },
    watch:{
      treeData:{
        handler: function (val) {
          console.log('left',val)
          this.initData(val)
        },
        deep: true,
        immediate: true
      }
    },
    methods: {
      uuid() {
        function s4 () {
          return Math.floor((1 + Math.random()) * 0x10000)
            .toString(16)
            .substring(1)
        }
        return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
          s4() + '-' + s4() + s4() + s4()
      },
      initData(list) {
        let obj = {}
        list.forEach((item, index) => {
          item.index = index
          !obj[item.zone] && (obj[item.zone] = [] )
          obj[item.zone].push(item)
        })

        let treeData = [{
          name: '测点集合',
          treeLevel: 0,
          treeId: this.uuid(),
          expand: true,
          originExpand: true,
          indeterminate: false,
          checked: false,
          visible: true,
          eyeVisible: true,
          children: []
        }]

        for (let key in obj) {

          let bItem = {
            name: key,
            treeLevel: 1,
            treeId: this.uuid(),
            expand: true,
            originExpand: true,
            indeterminate: false,
            checked: false,
            visible: true,
            eyeVisible: true,
            parentNode: treeData[0],
            children: []
          }
          treeData[0].children.push(bItem)
          treeData.push(bItem)

          let list = obj[key].map(item => {
            return {
              ...item,
              name: item.feature_name,
              treeLevel: 2,
              treeId: this.uuid(),
              expand: true,
              originExpand: true,
              indeterminate: false,
              checked: false,
              visible: true,
              eyeVisible: true,
              parentNode: bItem,
              children: []
            }
          })
          bItem.children = list
          treeData = treeData.concat(list)
        }

        this.dataList = [];
        this.searchValue = ''
        this.loading = true;

        setTimeout(() => {
          this.loading = false;
          this.dataList = treeData
        }, 500);
        
      },
      handleCheck(item) {
        this.checkIndexs = []
        item.children.length === 0 && this.checkIndexs.push(item.index)
        if (!(item.checked || item.indeterminate)) {
          console.log("取消选中")
          item.checked = false;
          item.indeterminate = false;
          this.updateRecursionNodeKey(item.children, "checked", false);
        } else {
          console.log("选中")
          console.log(item.checked)
          item.checked = true;
          item.indeterminate = false;
          this.updateRecursionNodeKey(item.children, "checked", true);
        }
        this.$emit('on-change', {
          type: 'check',
          bool: item.checked,
          indexs: this.checkIndexs
        })
        this.updateRecursionNodeKeyUp(item, "checked",);
      },
      // 树形的勾选眼睛事件
      onEyeVisible(item, visible) {
        item.eyeVisible = visible
        this.eyeIndexs = []
        item.children.length === 0 && this.eyeIndexs.push(item.index)
        this.updateRecursionNodeKey(item.children, "eyeVisible", visible)
        this.$emit('on-change', {
          type: 'eye',
          bool: visible,
          indexs: this.eyeIndexs
        })
        this.updateRecursionNodeKeyUp(item, 'eyeVisible')
      },
      toggleExpand(item) {
        item.expand = !item.expand;
        this.updateRecursionNodeKey(item.children, "visible", item.expand );
      },
      //向下递归节点 更新节点某个属性
      updateRecursionNodeKey(children, key, status) {
        children = children || [];
        children.forEach((node) => {
          node[key] = status;
          if (node.children && node.children.length) {
            if (key === "checked") {
              node.indeterminate = false;
              this.updateRecursionNodeKey(node.children, key, status);
            }
            if (key === "visible") {
              if (status) {
                if (node.expand) {
                  // 子节点是展开的，此时需要更新子节点的visible属性
                  this.updateRecursionNodeKey(node.children, key, status);
                }
              } else {
                console.log("关闭");
                // 关闭时把所有子节点都关闭
                node.expand = status;
                this.updateRecursionNodeKey(node.children, key, status);
              } 
            }
            if (key === 'eyeVisible') {
              this.updateRecursionNodeKey(node.children, key, status);
            }
          } else {
            if (key === "checked") {
              this.checkIndexs.push(node.index)
            }
            if (key === 'eyeVisible') {
              this.eyeIndexs.push(node.index)
            }
          }
        });
      },
      // 向上递归节点 更新节点indeterminate/checked
      updateRecursionNodeKeyUp(data, key) {
        const parentNode = data.parentNode;
        if (parentNode) {
          if (key === 'eyeVisible') {
            let filterVisibleNum = parentNode.children.filter(item => item.eyeVisible).length
            parentNode.eyeVisible = filterVisibleNum > 0
          }
          if (key === "checked") {
            let num = parentNode.children.length;
            let filterCheckedNum = parentNode.children.filter(item => item.checked).length
            let indeterminateIndex = parentNode.children.findIndex(item => item.indeterminate)
            if (num === filterCheckedNum) {
              parentNode.indeterminate = false;
              parentNode.checked = true;
            } else if (filterCheckedNum > 0 || indeterminateIndex > -1) {
              parentNode.indeterminate = true;
              parentNode.checked = false;
            } else {
              parentNode.indeterminate = false;
              parentNode.checked = false;
            }
          }
          this.updateRecursionNodeKeyUp(parentNode);
        }
        
      },

      // 获取选中的节点
      getCheckedNodes() {
        return this.dataList.filter((i) => i.checked);
      },
      
    },
  };
  </script>
  
  <style lang="less" scoped>
  /deep/ .vue-recycle-scroller__item-wrapper {
    overflow-x: auto;
  }
  
  .virtual-tree {
    &__list-view {
      position: relative;
      margin: 0;
      display: flex;
      white-space: nowrap;
    }
    &__arrow {
      width: 18px;
      height: 100%;
      display: inline-block;
      cursor: pointer;
      text-align: center;
      i {
        transition: all 0.2s ease-in-out;
        color: #d0d2d4;
        font-size: 16px;
      }
    }
    /deep/ .put-checkbox-wrapper {
      margin: 0 4px;
    }
    &__title {
      flex: 1;
      padding: 0 4px;
      height: 100%;
      display: flex;
      align-items: center;
    }
  }
  </style>
  